package com.it.a_jichu.b_数据类型;

/*
 * 数据类型
 * 【说明】：数据类型用来规定了变量只能存储什么类型的数据
 * 【类型】：
 *         整数类型
 *              byte：占用内存（1）数据范围（-128~127）超出会报错
 *              short：占用内存（2）数据范围（-32768 ~ 32767）
 *              int：占用内存（4）数据范围（10 位数（大概 21 亿多））
 *              long：占用内存（8）数据范围（19 位数）
 *         浮点类型
 *              float：占用内存（4）数据范围（-3.40E+38~3.40E+38）
 *              double：占用内存（8）数据范围（-1.79E+ 308~-1.79E+308）
 *         字符类型
 *              char：占用内存（2）数据范围（0 ~ 65535）
 *         布尔类型：
 *              boolean：占用内存（1）数据范围（true  false）
 *         2、引用数据类型
 */
class Type {
    public void test() {
        byte a = 1;
        System.out.println(a); // 1
        //a = 128; 报错原因：超出存储范围


        short b = 128;
        // 也不要给short赋值超过范围的数字！
        // b = 40000;
        // 结论：byte和short范围很小，平时不够用！很少使用！


        // int型（常用）
        int c = 88888;
        System.out.println(c);


        // long型（常用）
        // 如果要存储10位以上的整数，此时就可以使用long类型
        // 注意：给long类型变量赋值，字面量结尾需要加标记L或l，推荐L。明确的告诉计算机这个整数应该存储到long空间中
        long d = 10000000000L;
        // 有的时候赋值，字面量后不加L好像也可以
        // 原因：整数在Java中默认是存储给int类型的！所以计算机阅读这句代码的时候
        // 默认1000是int类型，然后将int类型的数字存储给long，由于Java有数据类型转换的规则，允许范围小的类型直接赋给范围大的类型，
        // 所以代码不报错！但是不建议这么做！
        long e = 1000;
        // 1.5 有的时候就会报错
        // 原因：10000000000已经是11位的数字，没有加L。默认整数是int类型，但是这个11位整数超过了int的范围，所以代码报错
        // long f = 10000000000;
        long f = 10000000000L;


        // 浮点型（小数型）
        // float：占用4个字节。也叫单精度型！
        // 注意：给float类型赋值字面量时，字面量结尾加标记F或f。如果不加标记，小数字面量默认是double类型
        // double类型的范围比float类型范围大，由于类型转换中规定：大范围的数据不能直接给小范围的空间赋值！
        // float g = 3.14;
        float g = 3.14F;


        // double型：占用8个自己。叫双精度型
        // double类型赋值字面量时，规范是给字面量结尾加D或d
        double h = 3.14D;
        // 不加也可以，因为小数字面量不加标记，默认就是double类型
        double j = 3.14;


        // 字符型：char，占用2个字节，由于计算机中有编码表，所以每一个字符都有一个数字对应。所以也有数字范围！
        char k = 'a';
        System.out.println(k);
        //由于计算机中有编码表，所以字符可以当成数字来使用
        //结果：98。因为编码表中'a'对应的数字是97，所以如果做加法就是拿97去运算！
        System.out.println(k + 1);
        //其实还可以把数字也给字符类型变量赋值（注意，这不是类型转换！）
        char l = 98;
        //注意：这不是把int转成了char。而是计算机根据编码表找到98对应的字符'b'，存到了l变量空间中
        System.out.println(l);


        //4.boolean型，占用1个字节。只有两个值true和false
        boolean m = true;
        boolean n = false;
    }
}

/*
 * 类型转换
 * 【说明】：类型范围小的变量，可以赋值给类型范围大的变量、所以类型转换分为自动类型转换和强制类型转换
 *         自动类型转换：类型范围小的变量赋值给类型范围大的变量，称为自动类型转换
 *         强制类型转换：如果将类型范围大的变量赋值给类型范围小的变量、会报错、所以就通过强制类型转换，但是会造成精度丢失
 * 【区别】：自动类型转换是Java自动执行的，而强制类型转换是自动类型提升的相反操作，需要我们自己手动执行
 */
class Typeof {
    public void test() {
        /*
         * 自动类型转换
         *  规则一：小的和大的运算，小的会变成大的，再运算！其中byte、short、char比较特殊，他们都会变成int再运算！
         *  规则二：byte、short、char很特殊，他们不管有没有遇到int，都会变成int再运算。因为他们的范围太小！
         */
        int a = 1;
        long b = 2L;
        float c = 3F;
        double d = 4;
        double num = a + b + c + d;
        System.out.println(num);
        // 总结：
        //  问：表达式的自动类型转换是什么样的?
        //  答：小范围的类型会自动变成大范围类型参与运算
        //  问：表达式的最终结果类型由谁决定？
        //  答：由最大的类型决定
        //  问：表达式有哪些类型转换需要注意？
        //  答：byte、short、char直接转换为 int 运算，因为他们三个的范围实在是太小了


        /**
         * 强制类型转换（手动实现）
         * 【语法】：数据类型 变量名 = （数据类型）被强转数据值;
         */
        int e = 1234;
        byte f = (byte) e;
        System.out.println(f);
        // 总结：
        //  问：强制类型转换需要注意什么？
        //  1. 可能会造成数据丢失
        //  2. 小鼠强制转换成整数是直接截断小数保留整数
        //  所以能不使用强制类型转换就不使用


        /**
         * String类型与基本数据类型的运算
         *      可以与String类型运算的类型 byte short int long float double char boolean
         *      String与基本数据类型只能做连接运算 使用加号 + 进行拼接
         *      String与基本数据类型只能做连接运算 使用加号 + 进行拼接
         */
        byte b1 = 127;
        short s1 = 1277;
        int i1 = 12777;
        long l1 = 1277777;
        String str1 = "" + b1 + s1+ i1 + l1;
        System.out.println(str1);
    }
}


public class main {
    public static void main(String[] args) {
        new Typeof().test();
    }
}
